#ifndef PROXY_ENCRY_CLIENT_CONNECT_H_
#define PROXY_ENCRY_CLIENT_CONNECT_H_

#include "proxy/encry/encrybase.h"

namespace proxy{

  enum ErrorType{
    ERROR_TYPE_WRITE_ERROR,
    ERROR_TYPE_READ_ERROR
  };

  class EncryClientConn : public boost::noncopyable,
    public boost::enable_shared_from_this < EncryClientConn > {
  public:
    typedef boost::shared_ptr<EncryClientConn> Ptr;
    
    typedef boost::function < void( EncryClientConn::Ptr encry_conn,
      const char* data, int size) > ConnReadCallback;
    typedef boost::function< void( EncryClientConn::Ptr encry_conn)> 
      ConnWriteCallback;
    typedef boost::function < void(EncryClientConn::Ptr encry_conn,
      const boost::system::error_code& err, ErrorType error_type) > 
      ConnErrorCallback;
    typedef boost::function < void(EncryClientConn::Ptr encry_conn,
      const boost::system::error_code& err) > ConnServerCallback;

    EncryClientConn(boost::asio::io_service &io_service);
    virtual ~EncryClientConn();

    void SetConnReadCallback(ConnReadCallback call_back){
      SingalConnRead = call_back;
    }
    void SetConnWriteCallback(ConnWriteCallback call_back){
      SignalConnWrite = call_back;
    }
    void SetConnErrorCallback(ConnErrorCallback call_back){
      SignalConnError = call_back;
    }
    void SetConnServerCallback(ConnServerCallback call_back){
      SingalConnServer = call_back;
    }
    bool Start(const std::string addr, uint16 port);
    void Stop();
    bool AsyncWriteData(char *data, int size);
    void StartReadEncryData();
  private:
    void HandleServerConnect(const boost::system::error_code& err);
    void HandleReadEncryData(const boost::system::error_code& err, int size);
    int  AnysisReadEncry(const char *buffer, int size);

    std::string &MakeClientKey();
    
    void HandleEncryWrite(const boost::system::error_code& err);
  private:
    static const int MAX_BUFFER_SIZE = 8192;
    char read_buffer_[MAX_BUFFER_SIZE];
    int remain_header_size_;

    boost::asio::io_service &io_service_;
    boost::asio::ip::tcp::socket socket_;
    bool is_write_encry_;
    bool is_read_encry_;
    unsigned char key_;
    std::string make_key_str_;
    ConnReadCallback SingalConnRead;
    ConnWriteCallback SignalConnWrite;
    ConnErrorCallback SignalConnError;
    ConnServerCallback SingalConnServer;
  };

}

#endif // PROXY_ENCRY_CLIENT_CONNECT_H_